using System;
using System.Collections.Generic;
using FluentTests.Framework.Verbs;
using System.Linq;

namespace FluentTests.Framework.VerbExtensions
{
    public static class VerbReferenceExtensions
    {
        public static void Null<T>(this Is<T> verb) 
        {
            var assertion = verb.EnsuredWrapperObject.AssertionProvider;
            if (verb.Negated)
                assertion.IsNotNull(verb.EnsuredWrapperObject.ActualValue);
            else
                assertion.IsNull(verb.EnsuredWrapperObject.ActualValue);
        }

        public static void InstanceOf<T>(this Is<T> verb, Type type)
        {
            var assertion = verb.EnsuredWrapperObject.AssertionProvider;
            if (verb.Negated)
                assertion.IsNotInstanceOfType(verb.EnsuredWrapperObject.ActualValue,type);
            else
                assertion.IsInstanceOfType(verb.EnsuredWrapperObject.ActualValue, type);
        }


        public static Condition<TType> InstanceOfType<TType>(this IIs verb)
        {
            var assertion = verb.AssertionProvider;
            if (verb.Negated)
                assertion.IsNotInstanceOfType(verb.ActualValue, typeof(TType));
            else
            {
                assertion.IsInstanceOfType(verb.ActualValue, typeof (TType));
                return new Condition<TType>(new EnsuredWrapper<TType>(verb.AssertionProvider,(TType) verb.ActualValue));
            }
            return null;
        }


        public static void SameAs<T>(this Verb<T> verb, object instance)
        {            
            Func<T, bool> shouldTrigger = arg => !ReferenceEquals(arg,instance);
            VerbAssert<T>.Assert(verb, shouldTrigger,"References are {not} the same");
        }

        public static void EqualTo<T>(this Verb<T> verb, T instance)
        {
            if (verb.EnsuredWrapperObject.ActualValue==null)
                verb.AssertionProvider.Fail("Value was null, expected {0}",instance);
            Func<T, bool> shouldTrigger = arg => !arg.Equals(instance);            
            VerbAssert<T>.Assert(verb, shouldTrigger, "Value {0} is {not} equal to {1}",
                                    verb.EnsuredWrapperObject.ActualValue, instance);
            
        }

    }
   
}